/*****************************************************************************
 * Copyright (c) 2022, Nations Technologies Inc.
 *
 * All rights reserved.
 * ****************************************************************************
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the disclaimer below.
 *
 * Nations' name may not be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
 * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * ****************************************************************************/

/**
 * @file main.c
 * @author Nations
 * @version V1.2.2
 *
 * @copyright Copyright (c) 2022, Nations Technologies Inc. All rights reserved.
 */
#include "main.h"
#include <stdio.h>
#include <stdint.h>

#include "sys_param.h"
#include "my_uart.h"
#include "my_power.h"
#include "my_basic_timer.h"
#include "HF_pwm_drv.h"
#include "HF_power.h"
#include "my_dac.h"
#include "EMS_pwm_drv.h"
#include "EMS_power.h"
#include "my_buzzer.h"
#include "my_motor.h"
#include "my_key_drv.h"
#include "rgb_spi_drv.h"
#include "includes.h"
// #include "my_adc_drv.h"
// #include "my_battery.h"
// #include "my_output_wave.h"

#include "menu.h"

/**
 * @brief  Inserts a delay time.
 * @param count specifies the delay time length.
 */
void Delay(uint32_t count)
{
    for (; count > 0; count--)
        ;
}

/**
 * @brief Assert failed function by user.
 * @param file The name of the call that failed.
 * @param line The source line number of the call that failed.
 */
#ifdef USE_FULL_ASSERT
void assert_failed(const uint8_t* expr, const uint8_t* file, uint32_t line)
{
    while (1)
    {
    }
}
#endif // USE_FULL_ASSERT

typedef  void (*pFunction)(void);

pFunction Jump_To_Application;
uint32_t JumpAddress;

// boot loader  占用22k
//#define APPLICATION_ADDRESS   (uint32_t)0x8006800

#define EASTRA_START_ADDRESS   (uint32_t)0x8005000
#define EASTRA_END_ADDRESS   (uint32_t)0x8008000

/* USER CODE BEGIN 0 */
void Jump_App_Handle(void)
{
    if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000)
    {
        printf("app fun check ok , jump to app -------------\r\n");
        JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
        Jump_To_Application = (pFunction) JumpAddress;
        __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
        /* Jump to application */
        Jump_To_Application();
    }
    printf("app fun not ok , still in bootlader\r\n");
}



/**
 * @brief  Main program.
 */

extern SYS_PARAM_t sys_data;

int main(void)
{
    uint32_t test_buff[100];
    uint32_t tmp_addr;
    int i;
    /*SystemInit() function has been called by startup file startup_n32l40x.s*/
	int task_1ms_cnt = 0 ;
	static int hf_ctrl_time = 0;
	int test_duty;
	int ems_duty_change = 0;
	int led_run_cnt = 0;
	int rgb_reset_flag = 0;
    int index = 0;

    uint8_t Test_Result = 0;
    uint32_t WRPR_Value = 0xFFFFFFFF, ProtectedPages = 0, ProgramData = 0xFFFFFF;


//--------------system init begin--------
    my_basic_timer_init();
    sys_power_init();	

    my_rgb_init();
    my_uart_init();

    printf("JE3 BOOTER LOADER begin -------------\r\n");
    my_key_init();


//FALSH WRITE TEST-----
    /* Configures the Internal High Speed oscillator */
    if(FLASH_HSICLOCK_DISABLE == FLASH_ClockInit()){
        printf("HSI oscillator not yet ready\r\n");
        while(1){
            // 空等待
        }
    }
		
    task_1ms_cnt = 0;
    while (task_1ms_cnt < 100){
        if(sys_data.task_1ms_flag){
            sys_data.task_1ms_flag = 0;
            task_1ms_cnt ++;
        }
    }
			
 /* Unlocks the FLASH Program Erase Controller */
    FLASH_Unlock();
    /* Get pages already write protection */
    WRPR_Value = FLASH_GetWriteProtectionOB();
    printf("WRPR_Value : 0x%0x\r\n", WRPR_Value);

#ifdef WRITE_PROTECTION_DISABLE

    printf("Write Protection Disable\r\n");
    /* Get pages already write protected */
    ProtectedPages = ~(WRPR_Value | FLASH_PROTECTED_PAGES);
	task_1ms_cnt = 0;
//	while (task_1ms_cnt < 100){
//        if(sys_data.task_1ms_flag){
//            sys_data.task_1ms_flag = 0;
//            task_1ms_cnt ++;
//        }
//    }
		
	 /* Erase all the option Bytes */
    FLASH_EraseOB();
		
	/* Get pages already write protection */
    WRPR_Value = FLASH_GetWriteProtectionOB();

    printf("WRPR_Value_second  : 0x%0x\r\n", WRPR_Value);
		
    /* Check if desired pages are already write protected */
    if ((WRPR_Value | (~FLASH_PROTECTED_PAGES)) != 0xFFFFFFFF)
    {
        printf(" erase all ob \r\n");
        /* Erase all the option Bytes */
        FLASH_EraseOB();

		task_1ms_cnt = 0;
//		while (task_1ms_cnt < 100)
//		{
//			if(sys_data.task_1ms_flag){
//				sys_data.task_1ms_flag = 0;
//				task_1ms_cnt ++;
//			}
//		}
        /* Check if there is write protected pages */
        // if (ProtectedPages != 0x0)
        // {
        //     /* Restore write protected pages */
        //     FLASH_EnWriteProtection(ProtectedPages);
        // }
        /* Generate System Reset to load the new option byte values */
        NVIC_SystemReset();
    }
#elif defined WRITE_PROTECTION_ENABLE
    // 写保护，会锁住芯片所在的扇区
    printf("Write Protection Enable\r\n");

    /* Set write protected pages */
    ProtectedPages = (~WRPR_Value) | FLASH_PROTECTED_PAGES;

    /* Check if desired pages are not yet write protected */
    if (((~WRPR_Value) & FLASH_PROTECTED_PAGES) != FLASH_PROTECTED_PAGES)
    {
        /* Erase all the option Bytes */
        FLASH_EraseOB();
        /* Enable the pages write protection */
        FLASH_EnWriteProtection(ProtectedPages);
        /* Generate System Reset to load the new option byte values */
        NVIC_SystemReset();
    }
    else
    {
        /* FLASH Write Protection Test */
        printf("Flash Page Erase/Program\r\n");
        /* Clear All pending flags */
        FLASH_ClearFlag(FLASH_STS_CLRFLAG);
	    task_1ms_cnt = 0;
		while (task_1ms_cnt < 100){
			if(sys_data.task_1ms_flag){
				sys_data.task_1ms_flag = 0;
				task_1ms_cnt ++;
			}
		}
        /* Erase */
        if (FLASH_ERR_WRP == FLASH_EraseOnePage(FLASH_WRITE_START_ADDR))
        {
            /* Clear All pending flags */
            FLASH_ClearFlag(FLASH_STS_CLRFLAG);
            /* Program */
            for(index = 0; index < 5; index++){
                if (FLASH_ERR_WRP == FLASH_ProgramWord(FLASH_WRITE_START_ADDR + index*4, ProgramData)){
                    /* Check */
                    if (ProgramData == (*(__IO uint32_t*)(FLASH_WRITE_START_ADDR + index*4))){
                        /* Test Fail */
                        Test_Result = FAILED;
                    }
                    else{
                        /* Test PASSED */
                        Test_Result = PASSED;
                    }
                }
                else{
                    /* Test Fail */
                    Test_Result = FAILED;
                }
                printf("Flash[0x%0x] : [0x%0x]\r\n", FLASH_WRITE_START_ADDR + index*4,  (*(__IO uint32_t*)(FLASH_WRITE_START_ADDR + index*4)));
            }
        }
        else
        {
            /* Test Fail */
            Test_Result = FAILED;
        }		
		printf("Test_Result :%d \r\n", Test_Result);
    }

#endif

	//-0x8006800 ----64个写入0x5a01，然后吸入64个0xaa02 
	
//   FLASH_Unlock();
//	// FLASH_EraseOnePage(APPLICATION_ADDRESS);
//   tmp_addr = APPLICATION_ADDRESS;
//   for(i = 0; i < 64; i++)
//   {
//       test_buff[i] = 0x02005a88;
//   }
//   
//   my_flash_write_32_data(&tmp_addr, test_buff, 64);
//		printf("tmp_addr_1:[0x%0x]\r\n", tmp_addr);

//   for(i = 0; i < 64; i++)
//   {
//       test_buff[i] = 0x02005599;
//   }
//   my_flash_write_32_data(&tmp_addr, test_buff, 64);
//		printf("tmp_addr_2:[0x%0x]\r\n", tmp_addr);
		
//------------------JUMP TO APP
//--------------------------

   if(GPIO_ReadInputDataBit(LEVEL_ADD_KEY_PORT, LEVEL_ADD_KEY_PIN) != Bit_RESET)
		{
			Jump_App_Handle();	// 如果按键不按下，则快速跳转到app区
		}


    printf(" BOOTER_LOADER_cycle \r\n");

    while (1)
    {
        if(sys_data.task_1ms_flag){
            task_1ms_cnt ++;

            if(0 == task_1ms_cnt%10){
                my_key_scanf();
            }

            if(0 == task_1ms_cnt%500){
                hf_ctrl_time ++;
                if(0 == hf_ctrl_time%10){
                }
                if(0 == hf_ctrl_time%2){
                    
                sys_data.run_time ++;
                if(GPIO_ReadInputDataBit(LEVEL_ADD_KEY_PORT, LEVEL_ADD_KEY_PIN) == Bit_RESET)
                {
                    if(sys_data.run_time > 2)
                    {
                        Main_Menu();
                    }
                }
                else{
                    Jump_App_Handle();
                }
                
                   


//				printf("bootloadr_run_time:[%d],sys_clor[%d]\r\n", sys_data.run_time, get_sys_rgb_color());
                }
                if(test_duty > 100){
                    test_duty = 0;
                }	 
            }
            sys_data.task_1ms_flag = 0;
            if(sys_data.run_time > 30)  // 30秒超时退出
            {
                sys_data.run_time = 0;
                Jump_App_Handle();
            }

        }
    }
}

/**
 * @}
 */
